﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.SharePoint;
using Quix;

namespace SyncLibrary
{
    class Program
    {
        [System.STAThreadAttribute()]
        [PreEmptive.Attributes.Setup(CustomEndpoint = "so-s.info/PreEmptive.Web.Services.Messaging/MessagingServiceV2.asmx")]
        [PreEmptive.Attributes.Teardown()]
        [PreEmptive.Attributes.Feature("Quix.SyncLibrary")]
        static void Main(string[] args)
        {
            if (args.Count() == 0)
            {
                PrintUsage();
            }
            else
            {
                try
                {
                    System.Collections.Hashtable tbl = Core.HashArgs(args);
                    if (!tbl.ContainsKey("-url") || !tbl.ContainsKey("-source") || !tbl.ContainsKey("-target"))
                    {
                        PrintUsage();
                    }
                    else
                    {
                        StartProcessing();
                        System.IO.StreamWriter sw = new System.IO.StreamWriter(Core.ConvertArgsToLogFile(tbl["-url"].ToString()));
                        string strSourceLibrary = "", strTargetLibrary = "", strSourceLibraryUrl = "", strTargetLibraryUrl = "";
                        DateTime datFilter = DateTime.MaxValue;
                        //List<string> l = new List<string>();
                        List<Quix.Folder> l = new List<Quix.Folder>();
                        //List<string> f = new List<string>();
                        List<Quix.Folder> f = new List<Quix.Folder>();
                        List<string> x = new List<string>();
                        Quix.Folder fol = new Quix.Folder();
                        bool blnUpdate = false, blnFoldersOnly = false, blnSpecialFolder = false;
                        strSourceLibrary = tbl["-source"].ToString();
                        strTargetLibrary = tbl["-target"].ToString();
                        if (tbl.ContainsKey("-foldersonly"))
                        {
                            if (tbl["-foldersonly"].ToString().ToLower() == "true")
                            {
                                blnFoldersOnly = true;
                            }
                        }
                        if (tbl.ContainsKey("-clearscreen"))
                        {
                            if (tbl["-clearscreen"].ToString().ToLower() == "true")
                            {
                                Console.Clear();
                                Console.CursorTop = 0;
                                Console.CursorLeft = 0;
                            }
                        }
                        if (tbl.ContainsKey("-date"))
                        {
                            try
                            { 
                                datFilter = Convert.ToDateTime(tbl["-foldersonly"].ToString());
                            }
                            catch {}
                        }
                        if (tbl.ContainsKey("-update"))
                        {
                            if (tbl["-update"].ToString().ToLower() == "true")
                            {
                                blnUpdate = true;
                                Console.ForegroundColor = ConsoleColor.Red;
                                Console.Write("UPDATING ");
                                sw.Write("UPDATING ");
                            }
                            else
                            {
                                Console.ForegroundColor = ConsoleColor.Green;
                                Console.Write("Comparing ");
                                sw.Write("Comparing ");
                            }
                        }
                        else
                        {
                            Console.ForegroundColor = ConsoleColor.Green;
                            Console.Write("Comparing ");
                            sw.Write("Comparing ");
                        }
                        if (tbl.ContainsKey("-foldersonly"))
                        {
                            if (tbl["-foldersonly"].ToString().ToLower() == "true")
                            {
                                blnFoldersOnly = true;
                            }
                        }
                        Console.ForegroundColor = ConsoleColor.Green;
                        Core.Log((string)"Site Collection [" + tbl["-url"].ToString().ToLower() + "] target library [" + strTargetLibrary + "] from source library [" + strSourceLibrary + "]...", sw);
                        if (blnFoldersOnly)
                        {
                            Core.Log((string)"Updating folders only, not documents...", sw);
                        }
                        Core.Log((string)"=".PadRight(78, '='), sw);
                        Console.ForegroundColor = ConsoleColor.White;
                        using (SPSite sps = new SPSite(tbl["-url"].ToString()))
                        {
                            using (SPWeb spw = sps.OpenWeb())
                            {
                                Core.Log("Site: " + spw.Url, sw);
                                foreach (SPList spl in spw.Lists)
                                {
                                    if ((spl.BaseType == SPBaseType.DocumentLibrary) && (spl.Title.ToLower() == strTargetLibrary.ToLower()))
                                    {
                                        strTargetLibraryUrl = spl.RootFolder.Url.ToLower();
                                        break;
                                    }
                                }
                                if (strTargetLibraryUrl.Trim().Length == 0)
                                {
                                    throw new Exception("The target library [" + strTargetLibrary + "] cannot be found!");
                                }
                                foreach (SPList spl in spw.Lists)
                                {
                                    if ((spl.BaseType == SPBaseType.DocumentLibrary) && (spl.Title.ToLower() == strSourceLibrary.ToLower()))
                                    {
                                        strSourceLibraryUrl = spl.RootFolder.Url.ToLower();
                                        foreach (SPListItem fld in spl.Folders)
                                        {
                                            //f.Add(fld.Url.ToLower().Replace(strSourceLibrary.ToLower(), strTargetLibrary.ToLower()));
                                            if (fld.Url.ToString().ToLower().Contains("_files/") || fld.Url.ToString().ToLower().Contains("_files"))
                                            {
                                                x.Add(fld.Url.ToString().ToLower());
                                                Core.Log(">>>Special Folder:" + fld.Url.ToString().ToLower(), sw);
                                            }
                                            else
                                            {
                                                fol = new Quix.Folder();
                                                fol.Author = fld[SPBuiltInFieldId.Author].ToString();
                                                fol.Editor = fld[SPBuiltInFieldId.Editor].ToString();
                                                fol.Created = Convert.ToDateTime(fld[SPBuiltInFieldId.Created].ToString());
                                                fol.Modified = Convert.ToDateTime(fld[SPBuiltInFieldId.Modified].ToString());
                                                fol.Url = fld.Url.ToLower().Replace(strSourceLibraryUrl, strTargetLibraryUrl);
                                                f.Add(fol);
                                                Core.Log("Folder: " + fld.Url.ToString().ToLower() + " queued...", sw);
                                                //f.Add(fld.Url.ToLower().Replace(strSourceLibraryUrl, strTargetLibraryUrl));
                                            }
                                        }
                                        foreach (SPListItem itm in spl.Items)
                                        {
                                            //l.Add(itm.Url.ToLower().Replace(strSourceLibrary.ToLower(), strTargetLibrary.ToLower()));
                                            if (x.Count > 0)
                                            {
                                                foreach (string s in x)
                                                {
                                                    if (itm.Url.ToString().ToLower().Contains(s))
                                                    {
                                                        blnSpecialFolder = true;
                                                        break;
                                                    }
                                                }
                                                if (!blnSpecialFolder)
                                                {
                                                    fol = new Quix.Folder();
                                                    fol.Author = itm[SPBuiltInFieldId.Author].ToString();
                                                    fol.Editor = itm[SPBuiltInFieldId.Editor].ToString();
                                                    fol.Created = Convert.ToDateTime(itm[SPBuiltInFieldId.Created].ToString());
                                                    fol.Modified = Convert.ToDateTime(itm[SPBuiltInFieldId.Modified].ToString());
                                                    fol.Url = itm.Url.ToLower().Replace(strSourceLibraryUrl, strTargetLibraryUrl);
                                                    l.Add(fol);
                                                    Core.Log("File: " + itm.Url.ToString().ToLower() + " queued...", sw);
                                                    //l.Add(itm.Url.ToLower().Replace(strSourceLibraryUrl, strTargetLibraryUrl));
                                                }
                                                else
                                                {
                                                    blnSpecialFolder = false;
                                                }
                                            }
                                            else
                                            {
                                                if (Convert.ToDateTime(itm[SPBuiltInFieldId.Modified].ToString()) < datFilter)
                                                {
                                                    fol = new Quix.Folder();
                                                    fol.Author = itm[SPBuiltInFieldId.Author].ToString();
                                                    fol.Editor = itm[SPBuiltInFieldId.Editor].ToString();
                                                    fol.Created = Convert.ToDateTime(itm[SPBuiltInFieldId.Created].ToString());
                                                    fol.Modified = Convert.ToDateTime(itm[SPBuiltInFieldId.Modified].ToString());
                                                    fol.Url = itm.Url.ToLower().Replace(strSourceLibraryUrl, strTargetLibraryUrl);
                                                    l.Add(fol);
                                                    Core.Log("File: " + itm.Url.ToString().ToLower() + " queued...", sw);
                                                    //l.Add(itm.Url.ToLower().Replace(strSourceLibraryUrl, strTargetLibraryUrl));
                                                }
                                            }
                                        }
                                        break;
                                    }
                                }
                                if (strSourceLibraryUrl.Trim().Length == 0)
                                {
                                    throw new Exception("The source library [" + strSourceLibrary + "] cannot be found!");
                                }
                                foreach (SPList spl in spw.Lists)
                                {
                                    //TODO: Need handler if libraries are renamed but the URL remains the same.
                                    if ((spl.BaseType == SPBaseType.DocumentLibrary) && (spl.Title.ToLower() == strTargetLibrary.ToLower()))
                                    {
                                        foreach (SPListItem fld in spl.Folders)
                                        {
                                            foreach (Quix.Folder qfl in f)
                                            {
                                                if (qfl.Url.ToString().ToLower() == fld.Url.ToString().ToLower())
                                                {
                                                    fol = qfl;
                                                    break;
                                                }
                                            }
                                            f.Remove(fol);
                                            Core.Log("Folder: " + fol.Url.ToString().ToLower() + " filtered...", sw);
                                            //f.Remove(fld.Url.ToLower());
                                        }
                                        if (blnUpdate)
                                        {
                                            SPFolderCollection sfc = spw.GetFolder(spl.Title).SubFolders;
                                            SPFolder spf;
                                            foreach (Quix.Folder qfl in f)
                                            {
                                                Core.Log("Adding: " + spl.RootFolder.Url + "/" + qfl.Url.ToLower().Replace(strTargetLibraryUrl.ToLower() + "/", "") + "...", sw);
                                                spf = sfc.Add(qfl.Url.ToLower());//.Replace(strTargetLibraryUrl.ToLower() + "/", ""));
                                                spf.Item[SPBuiltInFieldId.Author] = qfl.Author;
                                                spf.Item[SPBuiltInFieldId.Editor] = qfl.Editor;
                                                spf.Item[SPBuiltInFieldId.Created] = qfl.Created;
                                                spf.Item[SPBuiltInFieldId.Modified] = qfl.Modified;
                                                spf.Item.UpdateOverwriteVersion();
                                                Core.Log("Folder: " + spf.Url.ToString().ToLower() + " added to target...", sw);
                                            }
                                        }
                                        foreach (SPListItem itm in spl.Items)
                                        {
                                            foreach (Quix.Folder qfl in l)
                                            {
                                                if (qfl.Url.ToString().ToLower() == itm.Url.ToString().ToLower())
                                                {
                                                    fol = qfl;
                                                    break;
                                                }
                                            }
                                            l.Remove(fol);
                                            Core.Log("File: " + fol.Url.ToString().ToLower() + " filtered...", sw);
                                            ////l.Remove(itm.Url.ToLower());
                                        }
                                        break;
                                    }
                                }
                                foreach (Quix.Folder qfl in l)
                                {
                                    Core.Log("  " + qfl.Url.ToLower().Replace(strTargetLibrary.ToLower(), strSourceLibrary.ToLower()), sw);
                                    if (blnUpdate && !blnFoldersOnly)
                                    {
                                        try
                                        {
                                            {
                                                //itm.CopyTo(spw.Url.TrimEnd('/') + "/" + s);
                                                SPListItem itm = spw.GetListItem(spw.Url.TrimEnd('/') + "/" + qfl.Url.ToLower().Replace(strTargetLibraryUrl, strSourceLibraryUrl));
                                                itm.File.MoveTo(spw.Url.TrimEnd('/') + "/" + qfl.Url.ToLower());
                                                itm = spw.GetListItem(spw.Url.TrimEnd('/') + "/" + qfl.Url.ToLower());
                                                itm[SPBuiltInFieldId.Author] = qfl.Author;
                                                itm[SPBuiltInFieldId.Editor] = qfl.Editor;
                                                itm[SPBuiltInFieldId.Created] = qfl.Created;
                                                itm[SPBuiltInFieldId.Modified] = qfl.Modified;
                                                itm.UpdateOverwriteVersion();
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            Console.ForegroundColor = ConsoleColor.Red;
                                            Core.Log(ex.Message, sw);
                                            Console.ForegroundColor = ConsoleColor.White;
                                        }
                                    }
                                }
                                Core.Log("Total Folders = " + f.Count + ", Files = " + l.Count, sw);
                            }
                        }
                        sw.Flush();





                        StopProcessing();
                    }
                }
                catch (Exception ex)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine(ex.Message);
                }
            }
        }

        static void PrintUsage()
        {
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine(@"Usage is:\n  SyncLibrary.exe -url <URL> -source <SourceLibraryName> -target <TargetLibraryName> {-update <true/false>} {-clearscreen <true/false>}");
            Console.WriteLine(@"    -url <URL> - Site Collection URL to process e.g. http://www.crayveon.com/sites/Quix.");
            Console.WriteLine(@"    -source <SourceLibraryName> - The Title value of the source library to use in comparison.");
            Console.WriteLine(@"    -target <TargetLibraryName> - The Title value of the target library to use in comparison.");
            Console.WriteLine(@"    {-update <true/false>} - Optional parameter that forces the utility to update the Target library with missing content from the Source library.  By default, the operational mode of the utility is reporting only.");
            Console.WriteLine(@"    {-clearscreen <true/false>} - Optional parameter to clear the screen before output.");
            Console.WriteLine(@"    Example usage would be:");
            Console.WriteLine(@"    CompareLibraries.exe -url http://www.crayveon.com/sites/Quix -source DevPages -target DevPages2 -update true -clearscreen true");
        }


        [PreEmptive.Attributes.Feature("Quix.SyncLibrary", EventType = PreEmptive.Attributes.FeatureEventTypes.Start)]
        static void StartProcessing()
        {
        }

        [PreEmptive.Attributes.Feature("Quix.SyncLibrary", EventType = PreEmptive.Attributes.FeatureEventTypes.Stop)]
        static void StopProcessing()
        {
        }
    }
}
